const fs = require("fs-extra");
const path = require("path");

/**
 * npm引用模块，转换成require引用方式（简单粗暴，但存在问题）
 * @param {*} api
 * @param {*} opts
 */
function genWebpackExternals(api, opts = {}) {
  const { dependencies } = require(api.resolve("./package.json"));
  let externalsList = Object.keys(dependencies || {});
  let externals = {};
  externalsList.forEach(d => {
    // TODO Set external to be required during runtime
    externals[d] = `require("${d}")`;
  });
  return externals;
}
/**
 * 生成 webpack 打包配置文件
 * @param {*} api
 * @param {*} opts
 */
function genMainWebpackConfig(api, opts, entryName = "main") {
  const Config = require("webpack-chain");
  const webpackConfig = new Config();
  const mode = api.service.mode;

  webpackConfig
    .mode(mode)
    .devtool(false)
    .context(api.service.context)
    .target("electron-main")
    .externals(genWebpackExternals(api, opts));

  let entryWebpackOpts = opts.mainWebpacks && opts.mainWebpacks[entryName];
  if (!entryWebpackOpts)
    throw new Error(`Error whith entry = '${entryName}', Not Found Config.`);

  webpackConfig
    .entry(entryName)
    .add(`./${opts.srcDir}/${entryWebpackOpts.src}`);

  webpackConfig.output
    .path(api.resolve(path.join(opts.outputDir, entryWebpackOpts.out)))
    .filename(entryWebpackOpts.filename)
    .publicPath(entryWebpackOpts.publicPath || "");

  // prevent webpack from injecting mocks because
  // Electron runs in a native Node.js environment.
  webpackConfig.node.merge({
    __dirname: false,
    __filename: false
  });

  //
  return webpackConfig.toConfig();
}
/**
 * webpack打包文件
 * @param {*} api
 * @param {*} opts
 */
function webpackMain(api, opts) {
  const webpack = require("webpack");
  let promiseList = [];
  // 迭代打包多个主进程文件
  for (let key in opts.mainWebpacks) {
    promiseList.push(
      new Promise((resolve, reject) => {
        const mainWebpackConfig = genMainWebpackConfig(api, opts, key);
        webpack(mainWebpackConfig, async (err, stats) => {
          if (err) return reject(err);
          if (stats.hasErrors()) {
            let error_s = stats.compilation.errors[0];
            return reject(error_s || new Error(`Webpack failed with errors.`));
          }
          resolve();
        });
      })
    );
  }

  // package webpack
  return Promise.all(promiseList).then(res => {
    /* 生成一个 package.json 配置文件 */
    const pkg = require(api.resolve("./package.json"));
    let pkg_obj = {
      name: pkg.name,
      version: pkg.version,
      productName: pkg.productName || pkg.name,
      author: pkg.author || pkg.name,
      main: "main.electron.js"
    };
    fs.writeFileSync(
      `${opts.outputDir}/package.json`,
      JSON.stringify(pkg_obj, null, 2)
    );
  });
}

// urils.js
module.exports = {
  genWebpackExternals,
  genMainWebpackConfig,
  webpackMain
};
